package com.geqian.structure.service.impl;

import cn.hutool.core.io.IoUtil;
import com.geqian.structure.common.dto.TargetTableDto;
import com.geqian.structure.entity.NodeData;
import com.geqian.structure.entity.TableColumnInfo;
import com.geqian.structure.entity.TableInfo;
import com.geqian.structure.pojo.*;
import com.geqian.structure.common.ResponseResult;
import com.geqian.structure.db.JDBCUtils;
import com.geqian.structure.service.GeneratorService;
import com.geqian.structure.utils.WordToPdfUtils;
import com.geqian.structure.utils.WordUtils;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author geqian
 * @date 12:03 2023/7/12
 */
@Service
public class GeneratorServiceImpl implements GeneratorService {

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;


    @Override
    public ResponseResult<List<NodeData>> selectTableStructure() {

        return ResponseResult.success(JDBCUtils.getTableTree());
    }

    @SneakyThrows
    @Override
    public void preview(TargetTableDto targetTableDto, HttpServletResponse response) {
        byte[] wordBytes = generateWord(targetTableDto);
        byte[] pdfBytes = WordToPdfUtils.word2007ToPdf(wordBytes);
        response.setHeader("content-type", "application/octet-stream");
        response.setHeader("filename", URLEncoder.encode("数据库表结构" + ".pdf", "UTF-8"));
        //文件设置为附件
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("数据库表结构" + ".pdf", "UTF-8"));
        IoUtil.write(response.getOutputStream(), true, pdfBytes);
    }

    @SneakyThrows
    @Override
    public void download(TargetTableDto targetTableDto, HttpServletResponse response) {
        byte[] wordBytes = generateWord(targetTableDto);
        response.setHeader("content-type", "application/octet-stream");
        response.setHeader("filename", URLEncoder.encode("数据库表结构" + ".docx", "UTF-8"));
        //文件设置为附件
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("数据库表结构" + ".docx", "UTF-8"));
        IoUtil.write(response.getOutputStream(), true, wordBytes);
    }


    @SneakyThrows
    public byte[] generateWord(TargetTableDto targetTableDto) {
        TableColumnInfo.setFieldList(targetTableDto.getFieldList());
        WordUtils.WordBytesBuilder wordBytesBuilder = WordUtils.createWordBytesBuilder();
        List<NodeData> dataList = targetTableDto.getDataList();
        if (!CollectionUtils.isEmpty(dataList)) {
            List<NodeData> schemaList = targetTableDto.getDataList().stream().filter(data -> Objects.isNull(data.getSchema())).collect(Collectors.toList());
            WordUtils.ParagraphTextConfig tableDescConfig = WordUtils.createParagraphTextConfig()
                    .setFontFamily("宋体")
                    .setFontSize(20);
            WordUtils.ParagraphTextConfig tableCellConfig = WordUtils.createParagraphTextConfig()
                    .setFontFamily("宋体");
            for (NodeData schema : schemaList) {
                String schemaName = schema.getValue();
                wordBytesBuilder.addParagraphText("数据库 " + schemaName, tableDescConfig);
                List<NodeData> databaseDataList = dataList.stream().filter(data -> Objects.equals(data.getSchema(), schemaName)).collect(Collectors.toList());

                List<Future<DatabaseTable>> tableList = new ArrayList<>();
                for (NodeData databaseData : databaseDataList) {
                    Future<DatabaseTable> future = threadPoolExecutor.submit(() -> {
                                DatabaseTable databaseTable = new DatabaseTable();
                                TableInfo tableInfo = JDBCUtils.getTableInfo(schemaName, databaseData.getValue());
                                List<TableColumnInfo> tableColumnInfoList = JDBCUtils.getTableColumnInfoList(schemaName, databaseData.getValue());
                                databaseTable.setTableInfo(tableInfo);
                                databaseTable.setDataList(tableColumnInfoList);
                                return databaseTable;
                            }
                    );
                    tableList.add(future);
                }
                for (Future<DatabaseTable> future : tableList) {
                    DatabaseTable databaseTable = future.get();
                    TableInfo tableInfo = databaseTable.getTableInfo();
                    wordBytesBuilder.addParagraphText(!StringUtils.hasText(tableInfo.getTableComment()) ? tableInfo.getTableName() : tableInfo.getTableComment() + "  " + tableInfo.getTableName(), tableDescConfig.setFontSize(15));
                    wordBytesBuilder.addTable(databaseTable.getDataList(), tableCellConfig.setFontSize(10));
                    wordBytesBuilder.setCarriageReturn().setCarriageReturn();
                }
            }
        }
        return wordBytesBuilder.build();
    }
}